bitkeeper revision 1.1080 (40f50d9aaH0Dd_smhBdPvYcIQFbsoA)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 14 Jul 2004 10:40:26 +0000 (10:40 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 14 Jul 2004 10:40:26 +0000 (10:40 +0000)
Improved error handling in xend and XendClient.

16 files changed:
.rootkeys
tools/python/xen/xend/XendClient.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendError.py [new file with mode: 0644]
tools/python/xen/xend/server/SrvBase.py
tools/python/xen/xend/server/SrvConsole.py
tools/python/xen/xend/server/SrvConsoleDir.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/SrvDir.py
tools/python/xen/xend/server/SrvDmesg.py
tools/python/xen/xend/server/SrvDomain.py
tools/python/xen/xend/server/SrvDomainDir.py
tools/python/xen/xend/server/SrvNode.py
tools/python/xen/xend/server/domain.py
tools/python/xen/xend/server/netif.py

index 812f49c65a99b16998bbcaaeb7869f0e46944197..f11d07c06a216802398760acecf6523c8ff9bc40 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/python/xen/xend/XendDomain.py
 40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
 40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
+40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
 40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
 40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
 40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
index e412c1e74934642ffaca1f3d30df37786cfa9a81..91ba071dc00f38de584380df27db3e75c9fbb8cb 100644 (file)
@@ -13,6 +13,8 @@ import types
 from StringIO import StringIO
 import urlparse
 
+from twisted.protocols import http
+
 from encode import *
 import sxp
 import PrettyPrint
@@ -121,9 +123,9 @@ def xend_request(url, method, data=None):
     resp = conn.getresponse()
     if DEBUG: print resp.status, resp.reason
     if DEBUG: print resp.msg.headers
-    if resp.status in [204, 404]:
+    if resp.status in [ http.NO_CONTENT ]:
         return None
-    if resp.status not in [200, 201, 202, 203]:
+    if resp.status not in [ http.OK, http.CREATED, http.ACCEPTED ]:
         raise XendError(resp.reason)
     pin = sxp.Parser()
     data = resp.read()
@@ -135,7 +137,7 @@ def xend_request(url, method, data=None):
     val = pin.get_val()
     #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
     #    val = val[1]
-    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
+    if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err':
         raise XendError(val[1])
     if DEBUG: print '**val='; sxp.show(val); print
     return val
index a7877bd6cfd18122d639f7da443a4af1b74565b6..6715b57f6a691826e09f6133143beab9bb84b869 100644 (file)
@@ -21,6 +21,7 @@ import XendDomainInfo
 import XendConsole
 import XendMigrate
 import EventServer
+from XendError import XendError
 
 from xen.xend.server import SrvDaemon
 xend = SrvDaemon.instance()
@@ -324,9 +325,9 @@ class XendDomain:
         dom = int(id)
         dominfo = self.domain_get(dom)
         if not dominfo:
-            raise ValueError("Invalid domain: " + str(id))
+            raise XendError("Invalid domain: " + str(id))
         if dominfo.config:
-            raise ValueError("Domain already configured: " + str(id))
+            raise XendError("Domain already configured: " + str(id))
         def fn(dominfo):
             self._add_domain(dominfo.id, dominfo)
             return dominfo
@@ -575,7 +576,7 @@ class XendDomain:
         dom = int(dom)
         dominfo = self.domain_get(dom)
         if not dominfo:
-            raise ValueError("invalid domain:" + str(dom))
+            raise XendError("invalid domain:" + str(dom))
         self.refresh_schedule()
         return dominfo.device_create(devconfig)
 
@@ -589,7 +590,7 @@ class XendDomain:
         dom = int(dom)
         dominfo = self.domain_get(dom)
         if not dominfo:
-            raise ValueError("invalid domain:" + str(dom))
+            raise XendError("invalid domain:" + str(dom))
         self.refresh_schedule()
         return dominfo.device_destroy(type, idx)
 
index a9c4f5b492208c44ff237f855ed31a066f14bd80..be7803f7212b3f79cd71f96bfb7338c6a55a7159 100644 (file)
@@ -29,6 +29,8 @@ xendConsole = XendConsole.instance()
 import server.SrvDaemon
 xend = server.SrvDaemon.instance()
 
+from XendError import VmError
+
 """Flag for a block device backend domain."""
 SIF_BLK_BE_DOMAIN = (1<<4)
 
@@ -58,16 +60,6 @@ def shutdown_reason(code):
     """
     return shutdown_reasons.get(code, "?")
 
-class VmError(ValueError):
-    """Vm construction error."""
-
-    def __init__(self, value):
-        self.value = value
-
-    def __str__(self):
-        return self.value
-
-
 def blkdev_name_to_number(name):
     """Take the given textual block-device name (e.g., '/dev/sda1',
     'hda') and return the device number used by the OS. """
@@ -410,7 +402,11 @@ class XendDomainInfo:
                 self.autorestart = 1
             self.configure_backends()
             image = sxp.child_value(config, 'image')
+            if image is None:
+                raise VmError('missing image')
             image_name = sxp.name(image)
+            if image_name is None:
+                raise VmError('missing image name')
             image_handler = get_image_handler(image_name)
             if image_handler is None:
                 raise VmError('unknown image type: ' + image_name)
diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py
new file mode 100644 (file)
index 0000000..0e6c75e
--- /dev/null
@@ -0,0 +1,14 @@
+
+class XendError(ValueError):
+    
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return self.value
+
+class VmError(XendError):
+    """Vm construction error."""
+
+    pass
+
index 6ea92ae6cc15a6dcc781de8fda9bf5b961ae7643..048339e0b48461f6e33886122e6efae817cc27f1 100644 (file)
@@ -10,12 +10,15 @@ import StringIO
 from twisted.internet import defer
 #defer.Deferred.debug = 1
 from twisted.internet import reactor
+from twisted.protocols import http
 from twisted.web import error
 from twisted.web import resource
 from twisted.web import server
 
 from xen.xend import sxp
 from xen.xend import PrettyPrint
+from xen.xend.Args import ArgError
+from xen.xend.XendError import XendError
 
 def uri_pathlist(p):
     """Split a path into a list.
@@ -86,33 +89,45 @@ class SrvBase(resource.Resource):
         """
         op = req.args.get('op')
         if op is None or len(op) != 1:
-            req.setResponseCode(404, "Invalid")
+            req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request")
             return ''
         op = op[0]
         op_method = self.get_op_method(op)
         if op_method is None:
-            req.setResponseCode(501, "Not implemented")
+            req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op)
             req.setHeader("Content-Type", "text/plain")
-            req.write("Not implemented: " + op)
+            req.write("Operation not implemented: " + op)
             return ''
         else:
+            return self._perform(op, op_method, req)
+
+    def _perform(self, op, op_method, req):
+        try:
             val = op_method(op, req)
-            if isinstance(val, defer.Deferred):
-                val.addCallback(self._cb_perform, req, 1)
-                return server.NOT_DONE_YET
-            else:
-                self._cb_perform(val, req, 0)
-                return ''
+        except Exception, err:
+            return self._perform_err(err, req)
+            
+        if isinstance(val, defer.Deferred):
+            val.addCallback(self._perform_cb, req, dfr=1)
+            val.addErrback(self._perform_err, req, dfr=1)
+            return server.NOT_DONE_YET
+        else:
+            self._perform_cb(val, req, 0)
+            return ''
 
-    def _cb_perform(self, val, req, dfr):
+    def _perform_cb(self, val, req, dfr):
         """Callback to complete the request.
         May be called from a Deferred.
+
+        @param err: the error
+        @param req: request causing the error
+        @param dfr: deferred flag
         """
         if isinstance(val, error.ErrorPage):
             req.write(val.render(req))
         elif self.use_sxp(req):
             req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(val, req)
+            sxp.show(val, out=req)
         else:
             req.write('<html><head></head><body>')
             self.print_path(req)
@@ -126,6 +141,34 @@ class SrvBase(resource.Resource):
         if dfr:
             req.finish()
 
+    def _perform_err(self, err, req, dfr=0):
+        """Error callback to complete a request.
+        May be called from a Deferred.
+
+        @param err: the error
+        @param req: request causing the error
+        @param dfr: deferred flag
+        """
+        if not (isinstance(err, ArgError) or
+                isinstance(err, sxp.ParseError) or
+                isinstance(err, XendError)):
+            if dfr:
+                return err
+            else:
+                raise
+        if self.use_sxp(req):
+            req.setHeader("Content-Type", sxp.mime_type)
+            sxp.show(['xend.err', str(err)], out=req)
+        else:
+            req.setHeader("Content-Type", "text/plain")
+            req.write('Error in ')
+            req.write(op)
+            req.write(': ')
+            req.write(str(err))
+        if dfr:
+            req.finish()
+        
+
     def print_path(self, req):
         """Print the path with hyperlinks.
         """
index 59d0e5f11c1b4b77c35d1029fc12b41ee44a6805..eb8994425b998fedfb1c5f8658ccb9c104a3809a 100644 (file)
@@ -21,19 +21,22 @@ class SrvConsole(SrvDir):
         return self.perform(req)
         
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(self.info.sxpr(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            #self.ls()
-            req.write('<p>%s</p>' % self.info)
-            req.write('<p><a href="%s">Connect to domain %d</a></p>'
-                      % (self.info.uri(), self.info.dom2))
-            self.form(req)
-            req.write('</body></html>')
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-Type", sxp.mime_type)
+                sxp.show(self.info.sxpr(), out=req)
+            else:
+                req.write('<html><head></head><body>')
+                self.print_path(req)
+                #self.ls()
+                req.write('<p>%s</p>' % self.info)
+                req.write('<p><a href="%s">Connect to domain %d</a></p>'
+                          % (self.info.uri(), self.info.dom2))
+                self.form(req)
+                req.write('</body></html>')
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
 
     def form(self, req):
         req.write('<form method="post" action="%s">' % req.prePathURL())
index 814b44837078ff87c7fcb16dc2e90b323873b953..1371f6c0ef2f558fa33075f903e6f0b04e38b87f 100644 (file)
@@ -31,17 +31,20 @@ class SrvConsoleDir(SrvDir):
         return v
 
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_console(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_console(req)
-            #self.form(req.wfile)
-            req.write("</body></html>")
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-Type", sxp.mime_type)
+                self.ls_console(req, 1)
+            else:
+                req.write("<html><head></head><body>")
+                self.print_path(req)
+                self.ls(req)
+                self.ls_console(req)
+                #self.form(req.wfile)
+                req.write("</body></html>")
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
 
     def ls_console(self, req, use_sxp=0):
         url = req.prePathURL()
index e80b23334e12b476d5bd8a921684ab111ad8d199..fe47592b646a1d6c22ad1789b4fdf493101cbed6 100644 (file)
@@ -31,6 +31,7 @@ from xen.xend import sxp
 from xen.xend import PrettyPrint
 from xen.xend import EventServer
 eserver = EventServer.instance()
+from xen.xend.XendError import XendError
 
 from xen.xend.server import SrvServer
 
@@ -114,7 +115,7 @@ class MgmtProtocol(protocol.DatagramProtocol):
         """
         print name, req
         dom = sxp.child_value(req, 'domain')
-        if not dom: raise ValueError('Missing domain')
+        if not dom: raise XendError('Missing domain')
         dom = int(dom)
         console_port = sxp.child_value(req, 'console_port')
         if console_port:
@@ -131,11 +132,11 @@ class MgmtProtocol(protocol.DatagramProtocol):
     def op_console_disconnect(self, name, req):
         id = sxp.child_value(req, 'id')
         if not id:
-            raise ValueError('Missing console id')
+            raise XendError('Missing console id')
         id = int(id)
         console = self.daemon.get_console(id)
         if not console:
-            raise ValueError('Invalid console id')
+            raise XendError('Invalid console id')
         if console.conn:
             console.conn.loseConnection()
         return ['ok']
@@ -340,7 +341,7 @@ class EventProtocol(protocol.Protocol):
          return 'op_' + name.replace('.', '_')
 
     def operror(self, name, req):
-        raise NotImplementedError('Invalid operation: ' +name)
+        raise XendError('Invalid operation: ' +name)
 
     def dispatch(self, req):
         op_name = sxp.name(req)
@@ -371,7 +372,7 @@ class EventProtocol(protocol.Protocol):
     def op_console_disconnect(self, name, req):
         id = sxp.child_value(req, 'id')
         if not id:
-            raise ValueError('Missing console id')
+            raise XendError('Missing console id')
         self.daemon.console_disconnect(id)
         return ['ok']
 
@@ -707,7 +708,7 @@ class Daemon:
         """
         ctrl = self.blkifCF.getInstanceByDom(dom)
         if not ctrl:
-            raise ValueError('No blkif controller: %d' % dom)
+            raise XendError('No blkif controller: %d' % dom)
         print 'blkif_dev_create>', dom, vdev, mode, segment
         d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
         return d
@@ -740,7 +741,7 @@ class Daemon:
         """
         ctrl = self.netifCF.getInstanceByDom(dom)
         if not ctrl:
-            raise ValueError('No netif controller: %d' % dom)
+            raise XendError('No netif controller: %d' % dom)
         d = ctrl.attachDevice(vif, config, recreate=recreate)
         return d
 
@@ -769,7 +770,7 @@ class Daemon:
         """
         console = self.get_console(id)
         if not console:
-            raise ValueError('Invalid console id')
+            raise XendError('Invalid console id')
         console.disconnect()
 
     def domain_shutdown(self, dom, reason):
@@ -777,7 +778,7 @@ class Daemon:
         """
         ctrl = self.domainCF.getInstanceByDom(dom)
         if not ctrl:
-            raise ValueError('No domain controller: %d' % dom)
+            raise XendError('No domain controller: %d' % dom)
         ctrl.shutdown(reason)
         return 0
         
index c49c0b36ba9fd7c1a02ba6106983850423daf28c..106c5ef26874d47e5d1e498f8cff3a656e23457c 100644 (file)
@@ -1,9 +1,20 @@
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
+from twisted.protocols import http
 from twisted.web import error
+
 from xen.xend import sxp
+from xen.xend.XendError import XendError
+
 from SrvBase import SrvBase
 
+class SrvError(error.ErrorPage):
+
+    def render(self, request):
+        val = error.ErrorPage.render(self, request)
+        request.setResponseCode(self.code, self.brief)
+        return val
+
 class SrvConstructor:
     """Delayed constructor for sub-servers.
     Does not import the sub-server class or create the object until needed.
@@ -38,11 +49,17 @@ class SrvDir(SrvBase):
         self.table = {}
         self.order = []
 
+    def noChild(self, msg):
+        return SrvError(http.NOT_FOUND, msg, msg)
+
     def getChild(self, x, req):
         if x == '': return self
-        val = self.get(x)
+        try:
+            val = self.get(x)
+        except XendError, ex:
+            return self.noChild(str(ex))
         if val is None:
-            return error.NoResource('Not found')
+            return self.noChild('Not found ' + str(x))
         else:
             return val
 
@@ -59,16 +76,19 @@ class SrvDir(SrvBase):
         self.order.append(x)
 
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-type", sxp.mime_type)
-            self.ls(req, 1)
-        else:
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            self.ls(req)
-            self.form(req)
-            req.write('</body></html>')
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-type", sxp.mime_type)
+                self.ls(req, 1)
+            else:
+                req.write('<html><head></head><body>')
+                self.print_path(req)
+                self.ls(req)
+                self.form(req)
+                req.write('</body></html>')
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
             
     def ls(self, req, use_sxp=0):
         url = req.prePathURL()
index cadfd692e88f966842cbcfc6405adcd07e95a1ec..7580ecded7c893327b2fe2837149932f6352782b 100644 (file)
@@ -14,16 +14,19 @@ class SrvDmesg(SrvDir):
         self.xd = XendDmesg.instance()
 
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(['dmesg'] + self.info(), out=req)
-        else:
-            req.write('<html><head></head><body>')
-            req.write('<pre>')
-            self.print_path(req)
-            req.write(self.info()[0])
-            req.write('</pre></body></html>')
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-Type", sxp.mime_type)
+                sxp.show(['dmesg'] + self.info(), out=req)
+            else:
+                req.write('<html><head></head><body>')
+                req.write('<pre>')
+                self.print_path(req)
+                req.write(self.info()[0])
+                req.write('</pre></body></html>')
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
             
     def info(self):
         return self.xd.info()
index 3f01b6be97a1426527074a936c1a5d188d3aeb44..a3ec017622a7f391c4b6af55dab9e5d3b15676f2 100644 (file)
@@ -100,15 +100,8 @@ class SrvDomain(SrvDir):
         fn = FormFn(self.xd.domain_device_create,
                     [['dom', 'int'],
                      ['config', 'sxpr']])
-        try:
-            d = fn(req.args, {'dom': self.dom.id})
-            d.addErrback(self._op_device_create_err, req)
-            return d
-        except ValueError, ex:
-            return ['err', str(ex)]
-
-    def _op_device_create_err(self, err, req):
-        return ['err', str(err)]
+        d = fn(req.args, {'dom': self.dom.id})
+        return d
 
     def op_device_destroy(self, op, req):
         fn = FormFn(self.xd.domain_device_destroy,
index 4c1fd4e14fd485391fd36b76890055a9e2291689..130072c87142e2879b14ceb1a430ccfcee03624c 100644 (file)
@@ -9,6 +9,7 @@ from twisted.web import error
 from xen.xend import sxp
 from xen.xend import XendDomain
 from xen.xend.Args import FormFn
+from xen.xend.XendError import XendError
 
 from SrvDir import SrvDir
 from SrvDomain import SrvDomain
@@ -23,13 +24,10 @@ class SrvDomainDir(SrvDir):
 
     def domain(self, x):
         val = None
-        try:
-            dom = self.xd.domain_get(x)
-            if not dom: raise KeyError('No such domain')
-            val = SrvDomain(dom)
-        except KeyError, ex:
-            print 'SrvDomainDir>', ex
-            pass
+        dom = self.xd.domain_get(x)
+        if not dom:
+            raise XendError('No such domain ' + str(x))
+        val = SrvDomain(dom)
         return val
 
     def get(self, x):
@@ -44,6 +42,7 @@ class SrvDomainDir(SrvDir):
         Expects the domain config in request parameter 'config' in SXP format.
         """
         ok = 0
+        errmsg = ''
         try:
             configstring = req.args.get('config')[0]
             print 'config:', configstring
@@ -55,12 +54,12 @@ class SrvDomainDir(SrvDir):
         except Exception, ex:
             print 'op_create> Exception in config', ex
             traceback.print_exc()
+            errmsg = 'Configuration error ' + str(ex)
+        except sxp.ParseError, ex:
+            errmsg = 'Invalid configuration ' + str(ex)
         if not ok:
-            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
-            return "Invalid configuration"
-            return error.ErrorPage(http.BAD_REQUEST,
-                                   "Invalid",
-                                   "Invalid configuration")
+            req.setResponseCode(http.BAD_REQUEST, errmsg)
+            return errmsg
         try:
             deferred = self.xd.domain_create(config)
             deferred.addCallback(self._op_create_cb, configstring, req)
@@ -71,10 +70,6 @@ class SrvDomainDir(SrvDir):
             traceback.print_exc()
             req.setResponseCode(http.BAD_REQUEST, "Error creating domain: " + str(ex))
             return str(ex)
-            #return error.ErrorPage(http.BAD_REQUEST,
-            #                       "Error creating domain",
-            #                       str(ex))
-                                   
 
     def _op_create_cb(self, dominfo, configstring, req):
         """Callback to handle deferred domain creation.
@@ -113,7 +108,7 @@ class SrvDomainDir(SrvDir):
                     [['file', 'str']])
         deferred = fn(req.args)
         deferred.addCallback(self._op_restore_cb, req)
-        deferred.addErrback(self._op_restore_err, req)
+        #deferred.addErrback(self._op_restore_err, req)
         return deferred
 
     def _op_restore_cb(self, dominfo, req):
@@ -140,17 +135,20 @@ class SrvDomainDir(SrvDir):
         return self.perform(req)
 
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            self.ls_domain(req, 1)
-        else:
-            req.write("<html><head></head><body>")
-            self.print_path(req)
-            self.ls(req)
-            self.ls_domain(req)
-            self.form(req)
-            req.write("</body></html>")
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-Type", sxp.mime_type)
+                self.ls_domain(req, 1)
+            else:
+                req.write("<html><head></head><body>")
+                self.print_path(req)
+                self.ls(req)
+                self.ls_domain(req)
+                self.form(req)
+                req.write("</body></html>")
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
 
     def ls_domain(self, req, use_sxp=0):
         url = req.prePathURL()
index fadd32309e90f404188833b67cd7d063978099fe..e99526fabf45dd3e3bf0caa05a22853c02c16ed2 100644 (file)
@@ -45,22 +45,25 @@ class SrvNode(SrvDir):
         return self.perform(req)
 
     def render_GET(self, req):
-        if self.use_sxp(req):
-            req.setHeader("Content-Type", sxp.mime_type)
-            sxp.show(['node'] + self.info(), out=req)
-        else:
-            url = req.prePathURL()
-            if not url.endswith('/'):
-                url += '/'
-            req.write('<html><head></head><body>')
-            self.print_path(req)
-            req.write('<ul>')
-            for d in self.info():
-                req.write('<li> %10s: %s' % (d[0], str(d[1])))
-            req.write('<li><a href="' +url + 'dmesg">Xen dmesg output</a>')
-            req.write('</ul>')
-            req.write('</body></html>')
-        return ''
+        try:
+            if self.use_sxp(req):
+                req.setHeader("Content-Type", sxp.mime_type)
+                sxp.show(['node'] + self.info(), out=req)
+            else:
+                url = req.prePathURL()
+                if not url.endswith('/'):
+                    url += '/'
+                req.write('<html><head></head><body>')
+                self.print_path(req)
+                req.write('<ul>')
+                for d in self.info():
+                    req.write('<li> %10s: %s' % (d[0], str(d[1])))
+                req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
+                req.write('</ul>')
+                req.write('</body></html>')
+            return ''
+        except Exception, ex:
+            self._perform_err(ex, req)
             
     def info(self):
         return self.xn.info()
index 683d352ec0c41d02b95b8d10c3dc493a50084bc8..3a07c09b97c8444c2a51e40b9937d5eb5e1c1036 100644 (file)
@@ -1,5 +1,7 @@
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
+from xen.xend.XendError import XendError
+
 import channel
 import controller
 from messages import *
@@ -57,6 +59,6 @@ class DomainController(controller.Controller):
         """
         msgtype = self.reasons.get(reason)
         if not msgtype:
-            raise ValueError('invalid reason:' + reason)
+            raise XendError('invalid reason:' + reason)
         msg = packMsg(msgtype, {})
         self.writeRequest(msg)
index 894dc85832dd4dbc0ff0e0772288269638214bf1..1cbbe67ec8ed9e4d38be99329f9dcad7dccae988 100755 (executable)
@@ -8,6 +8,7 @@ from twisted.internet import defer
 from xen.xend import sxp
 from xen.xend import PrettyPrint
 from xen.xend import Vifctl
+from xen.xend.XendError import XendError
 
 import channel
 import controller
@@ -123,9 +124,9 @@ class NetDev(controller.Dev):
         self.ipaddr = None
         
         vmac = sxp.child_value(config, 'mac')
-        if not vmac: raise ValueError("invalid mac")
+        if not vmac: raise XendError("invalid mac")
         mac = [ int(x, 16) for x in vmac.split(':') ]
-        if len(mac) != 6: raise ValueError("invalid mac")
+        if len(mac) != 6: raise XendError("invalid mac")
         self.mac = mac
 
         self.bridge = sxp.child_value(config, 'bridge')